/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						       button.h

	$Header: /game/button.h $

	$NoKeywords: $

 ************************************************************************/

#ifndef BUTTON_H_INCLUDED
#define BUTTON_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <vector>

#include "bitmap_group_ptr.h"
#include "button_ptr.h"
#include "font_cache.h"
#include "game_window.h"
#include "handler.h"
#include "override_input_handler.h"
#include "pixel_24.h"
#include "text_window.h"

class  t_button;
class  t_button_bitmaps;
struct t_mouse_event;

typedef t_handler_1<t_button*> t_button_handler;


// --------------------------------------------------------
// button class
// --------------------------------------------------------
class t_button : public t_window
{
public:
	// constructors
    t_button( t_cached_ptr<t_button_bitmaps>& bitmaps, t_screen_point point,
		      t_window* parent, std::string const& text = "" );
	t_button( t_screen_point point, t_window* parent ); // start with no images.	

	// add text to the button.  Does not remove old text.
	void         add_text( std::string const& text, t_cached_font& font,
		                   t_pixel_24 const& color = t_pixel_24(0,0,0),
						   t_pixel_24 const& highlight_color = t_pixel_24(0,0,0),
						   t_pixel_24 const& disabled_color = t_pixel_24(100,100,100),
		                   bool drop_shadow = true, 
						   t_pixel_24 const& drop_shadow_color = t_pixel_24(200,200,200));
	// enable / disable button.  Button cannot be pressed while disabled, and shows
	// a special image.
    void             enable( bool arg = true );
	virtual t_window* get_child( t_screen_point point, bool ignore_visibility = false );  // find window from client coordinates
	t_button_handler get_click_handler() const;
	t_button_handler get_down_click_handler() const;
	// true if a point is within the button
	virtual bool     is_contained( t_screen_point point ) const; 
	bool             is_enabled() const;
	bool             is_pressed() const;
  virtual void     left_button_down( t_mouse_event const& event ); 
  virtual void     left_button_up( t_mouse_event const& event );
	virtual void     left_double_click( t_mouse_event const& event );
  virtual void     mouse_leaving( t_window* old_window, t_window* new_window,
		                            t_mouse_event const& event );
  virtual void     mouse_move( t_mouse_event const& event );
	
	virtual void     right_button_up( t_mouse_event const& event );
	// set callback handler for click.
	void             set_click_handler( t_button_handler const& function );
	void		     set_down_click_handler( t_button_handler const& function );
	// set image for disabled state.
	void		     set_disabled_image( t_window* window );
	void             set_double_click_handler( t_button_handler function );
	void             set_right_click_handler( t_button_handler const& function );
	void             set_highlighted( bool arg = true );
	// set highlighted image.
	void		     set_highlighted_image( t_window* window );
	void             set_pressed( bool arg = true );
	// set highlighted pressed image.
	void		     set_highlighted_pressed_image( t_window* window );
	// set pressed image.
	void		     set_pressed_image( t_window* window );
	void		     set_released_image( t_window* window );
    void             set_text( std::string const& text );
	virtual void     update_size();          // update the size of the button based on new images
	virtual void     update_transparency(); // update m_transparent flag based on child windows
protected:
	t_screen_rect compute_size();         // compute the new size of the button
	void          set_image();            // select the correct child window based on state

    t_cached_ptr<t_button_bitmaps> m_bitmaps;      // images for button.  can be null.
	t_button_handler       m_clicked;      // handler to call when button clicked.
	t_button_handler			 m_down_clicked; // handler to call when left button is pressed (not up)
	t_button_handler       m_double_clicked;    // function for double clicks
	t_button_handler       m_right_clicked;     // function for right clicks.
	t_window_ptr           m_current_image; // currently visible child.
    bool                 m_disabled;          // true if button is disabled
	t_window_ptr				   m_disabled_image;    // image to show while disabled
	t_screen_rect				   m_disabled_rect;		// text rect
    bool                 m_highlighted;       // true if button is highlighted
	t_window_ptr				   m_highlighted_image; // image to show when highlighted
	t_screen_rect				   m_highlighted_rect;	// text rect
	t_window_ptr				   m_highlighted_pressed_image; // image to show for pressed, highlighted button
	t_screen_rect				   m_highlighted_pressed_rect; // text rect
  bool                   m_pressed;           // true if button is pressed
	t_window_ptr				   m_pressed_image;     // image to show when pressed
	t_screen_rect				   m_pressed_rect;		// text rect
	t_window_ptr           m_released_image;    // default image.
	t_screen_rect				   m_released_rect;		// text rect
    
	t_text_window*         m_disabled_text_window;
	t_text_window*         m_highlighted_text_window;
	t_text_window*				 m_highlighted_pressed_text_window;
	t_text_window*         m_pressed_text_window;
	t_text_window*         m_released_text_window;
};

// --------------------------------------------------------
// inlines for button class
// --------------------------------------------------------

inline void t_button::enable( bool arg )
{
	if (m_disabled == arg)
	{
		m_disabled = !arg;
		set_image();
	}
}

inline bool t_button::is_enabled() const
{
	return !m_disabled;
}

inline bool t_button::is_pressed() const
{
	return m_pressed;
}

inline t_button_handler t_button::get_click_handler() const
{
	return m_clicked;
}

inline t_button_handler t_button::get_down_click_handler() const
{
	return m_down_clicked;
}

inline void t_button::set_click_handler( t_button_handler const& function )
{
	m_clicked = function;
}

inline void t_button::set_down_click_handler( t_button_handler const& function )
{
	m_down_clicked = function;
}

inline void t_button::set_double_click_handler( t_button_handler function )
{
	m_double_clicked = function;
}

inline void t_button::set_right_click_handler( t_button_handler const& function )
{
	m_right_clicked = function;
}

inline void t_button::set_pressed_image( t_window* window )
{
	m_pressed_image = window;
	update_size();
	set_image();
}

inline void t_button::set_released_image( t_window* window )
{
	m_released_image = window;
	update_size();
	set_image();
}

inline void t_button::set_highlighted_image( t_window* window )
{
	m_highlighted_image = window;
	update_size();
	set_image();
}

inline void t_button::set_highlighted_pressed_image( t_window* window )
{
	m_highlighted_pressed_image = window;
	update_size();
	set_image();
}

inline void t_button::set_disabled_image( t_window* window )
{
	m_disabled_image = window;
	update_size();
	set_image();
}

void	  set_button_layers( t_button* button, t_bitmap_group_ptr bitmaps, std::string name );
t_button* create_button( t_bitmap_group_ptr bitmaps, std::string name, t_window* parent,
						 t_screen_point origin = t_screen_point(0,0) );

#endif // BUTTON_H_INCLUDED
